package me.luger.project.fof.service;

import me.luger.core.commom.util.DateUtil;
import me.luger.core.commom.util.JsonUtil;
import me.luger.core.commom.util.LogUtil;
import me.luger.core.dao.nutz.service.BaseService;
import me.luger.project.fof.entity.FofTask;
import me.luger.project.fof.entity.ext.TaskParams;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.map.HashedMap;
import org.nutz.dao.Dao;
import me.luger.project.fof.entity.FundNav;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;

import java.util.*;

@Repository
public class FundNavService extends BaseService<FundNav> {
    public FundNavService(Dao dao) {
        super(dao);
    }

    public List<FundNav> getFundNavTrendByDateRange(String fundExtCode,Date startDate,Date endDate){
        StringBuilder sqlBuilder = new StringBuilder("select fund_ext_code,swanav,statistic_date from fund_nav where fund_ext_code = @fundExtCode ");
        if(null != startDate){
            sqlBuilder.append("and statistic_date >= @startDate ");
        }
        if(null != endDate){
            sqlBuilder.append("and statistic_date <= @endDate ");
        }
        Sql sql = Sqls.create(sqlBuilder.toString());
        sql.params().set("fundExtCode",fundExtCode);
        sql.params().set("startDate",startDate);
        sql.params().set("endDate",endDate);
        List<FundNav> navList = this.list(sql);

        //补充一个最近的净值记录，以保证每个基金列表中最少有一条记录；在调用fullFundNavList时，可以将净值填充完整
        if(navList == null || navList.size() < 1) {
            if(startDate == null) {
                startDate = new Date();
            }
            sqlBuilder = new StringBuilder("select fund_ext_code,swanav,statistic_date from fund_nav where fund_ext_code = @fundExtCode and statistic_date < @startDate order by statistic_date desc limit 1");
            sql = Sqls.create(sqlBuilder.toString());
            sql.params().set("fundExtCode",fundExtCode);
            sql.params().set("startDate",startDate);
            navList = this.list(sql);
        }
        return navList;
    }

    public List<FundNav> fullFundNavList(List<FundNav> fundNavList,Date startDate,Date endDate) {
        TreeMap<String,FundNav> fundNavMap = new TreeMap<String, FundNav>();


        for(FundNav fundNav : fundNavList){
            fundNavMap.put(fundNav.statisticDateStr(),fundNav);
        }

        if(fundNavMap.size() < 1) {
            return null;
        }
        FundNav startFundNav = fundNavMap.firstEntry().getValue();
        if(startDate == null){
            startDate = fundNavList.get(0).getStatisticDate();
        }
        //循环的最早一天
        Date firstDate = startDate;

        while (startDate.before(endDate)){
            try {
                String curDateFmt = DateUtil.format(startDate,DateUtil.DATE_YYYY_MM_DD);
                FundNav tempFundNav = fundNavMap.get(curDateFmt);
                if(null == tempFundNav){
                    tempFundNav = (FundNav) BeanUtils.cloneBean(startFundNav);
                    //获取的基金净值比统计的第一天还要早的话，需要把这个净值作为第一天的净值，但是把获取的这个比startDate更早的基金净值排除在外
                    if(tempFundNav.getStatisticDate().before(startDate) && firstDate.equals(startDate)) {
                        String rmvDate = DateUtil.format(tempFundNav.getStatisticDate(),DateUtil.DATE_YYYY_MM_DD);
                        fundNavMap.remove(rmvDate);
                    }
                    tempFundNav.setStatisticDate(DateUtil.parseDate(curDateFmt,DateUtil.DATE_YYYY_MM_DD));
                    fundNavMap.put(curDateFmt,tempFundNav);
                }

                startFundNav = fundNavMap.get(curDateFmt);
                startDate = DateUtil.add(startDate,24 * 60 * 60);
            }catch (Exception e){
                LogUtil.errorLog(e,"");
            }

        }

        fundNavList = new ArrayList<FundNav>();
        fundNavList.addAll(fundNavMap.values());
        return fundNavList;
    }


    public List<Map<String,Object>> getFundsTrendByDateRange(String[] fundExtCodes,Date startDate,Date endDate){
        List<Map<String,Object>> fundsTrendMapList = new ArrayList<Map<String, Object>>();

        List<FundNav> fundNavList = null;
        Map<String,Object> fundTrendMap = null;
        FundNav fundNav = null;
        for(String fundExtCode : fundExtCodes){
            fundNav = fetchById(fundExtCode);
            if(null == fundNav){
                continue;
            }
            fundNavList = getFundNavTrendByDateRange(fundExtCode,startDate,endDate);
            fundNavList = fullFundNavList(fundNavList,startDate,endDate);
            fundTrendMap = new HashedMap();

            Map<String,Object> datePriceMap = null;
            List<Map> datePriceMapList = new ArrayList<Map>();

            //设置基金回测净值的初始值为1，其他天按照这个值进行调整
            Double adjustSacle = new Double(1);
            int iteration = 0;
            if(fundNavList != null && fundNavList.size() > 0) {
                for(FundNav item : fundNavList){
                    if(iteration == 0) {
                        adjustSacle = item.getSwanav();
                    }
                    datePriceMap = new HashedMap();
                    datePriceMap.put("date",DateUtil.format(item.getStatisticDate(),DateUtil.DATE_YYYY_MM_DD));
                    datePriceMap.put("price",item.getSwanav() / adjustSacle);
                    datePriceMapList.add(datePriceMap);
                    iteration++;
                }
            }

            fundTrendMap.put("priceList",datePriceMapList);
            fundTrendMap.put("name",fundNav.getFundName());
            fundTrendMap.put("extCode",fundExtCode);
            fundsTrendMapList.add(fundTrendMap);
        }
        return fundsTrendMapList;
    }


    @Cacheable(value = "long_time_cache")
    public List<Map<String,Object>> getFundNavPriceTrendChart(FofTask task) {
        String paramStr = task.getParams();
        TaskParams taskParams = JsonUtil.parse(paramStr,TaskParams.class);
        String modelId = taskParams.getModelId();
        String backYear = "1";
        if ("1".equals(modelId)) {
            backYear = taskParams.getModelParams().get(1).getValue();
        } else if ("2".equals(modelId)) {
            backYear = taskParams.getModelParams().get(0).getValue();
        } else if ("3".equals(modelId)) {
            backYear = taskParams.getModelParams().get(0).getValue();
        } else if ("4".equals(modelId)) {

        }
        Calendar startCal = DateUtil.nowAsCalendar();
        Date startDate = null;
        Date endDate = DateUtil.nowAsDate();
        if("1".equals(backYear)){
            startCal.add(Calendar.YEAR,-1);
        }else if("2".equals(backYear)){
            startCal.add(Calendar.YEAR,-3);
        }else if("3".equals(backYear)){
            startCal.add(Calendar.YEAR,-5);
        }

        startDate = startCal.getTime();

        List<TaskParams.UpDownParamsBean> upDownParamsBeanList = taskParams.getUpDownParams();

        List<String> extCodeList = new ArrayList<String>();
        for(TaskParams.UpDownParamsBean item : upDownParamsBeanList){
            extCodeList.add(item.getId());
        }
        return getFundsTrendByDateRange(extCodeList.toArray(new String[]{}),startDate,endDate);

    }

    /**
     * 查询一个基金净值最早一天
     * @param fundExtCode
     * @return
     */
    public FundNav getFundNavFirstDay(String fundExtCode){
        StringBuilder sqlBuilder = new StringBuilder("select statistic_date from fund_nav where fund_ext_code = @fundExtCode order by statistic_date asc limit 1");
        Sql sql = Sqls.create(sqlBuilder.toString());
        sql.params().set("fundExtCode",fundExtCode);
        List<FundNav> navList = this.list(sql);
        if(navList != null && navList.size() > 0)
            return navList.get(0);
        else return null;
    }

}
